home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / Core Utilities / Exceptions.h < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-10  |  9.6 KB  |  329 lines  |  [TEXT/CWIE]

  1. #ifndef __EXCEPTIONS__
  2. #define __EXCEPTIONS__
  3. #pragma once
  4.  
  5. #ifndef __RESOURCES__
  6. #include <Resources.h>
  7. #endif
  8. #ifndef __MEMORY__
  9. #include <Memory.h>
  10. #endif
  11. #ifndef __APPLEEVENTS__
  12. #include <AppleEvents.h>
  13. #endif
  14.  
  15. #include <stddef.h>
  16. #include <stdarg.h>
  17. #include <limits.h>
  18. #include <string.h>
  19.  
  20. //
  21. // Our error codes
  22. //
  23. const OSErr ePointerNil                = -110;
  24. const OSErr eGeneralErr                = -1;
  25. const OSErr eAssertionFailure        = -30000;
  26. const OSErr eRequirementNotMet        = -30001;
  27. const OSErr eValueOutOfRange        = -30002;
  28. const OSErr eIndexOutOfRange        = -30003;
  29. const OSErr eLinksCorrupt            = -30004;
  30. const OSErr eDataCorrupt            = -30005;
  31. const OSErr eWrongDataType            = -30006;
  32. const OSErr eMenuIDNotMenuRID         = -30007;
  33.  
  34.  
  35. #include "LocationInCode.h"
  36.  
  37. // Note that this MUST be a macro to be useful. We may be able to get the
  38. // macsbug name later
  39.  
  40. #define GetLocationInCode()    LocationInCode(__LINE__, __FILE__)
  41.  
  42. extern    LocationInCode    gLocationInCode;
  43.  
  44. #define    SETUP_LOCATION    (gLocationInCode.fLineNum = __LINE__, gLocationInCode.fFileName = __FILE__, gLocationInCode)
  45. #define LOCATION_PARAM    const LocationInCode&    where = LOCATION
  46. #define LOCATION        gLocationInCode
  47.  
  48. //#define LOCATION_PARAM    const LocationInCode&    where = GetLocationInCode()
  49.  
  50.  
  51. //
  52. //    Useful va_arg utilitiies
  53. //
  54. typedef OSStatus (*VAProc)(va_list);
  55.  
  56. #define VADynamicCast(ap, T)                    (dynamic_cast<T>(va_arg(args, T)))
  57. #define VAStaticCast(ap, T)                        (static_cast<T> (va_arg(args, T)))
  58. #define VA_ARG(T, name, ap)                        T name = va_arg(ap, T)
  59. #define VA_ARG_DEFAULT(T, name, ap, val)        T name = ap ? va_arg(ap, T) : val
  60.  
  61.  
  62. //------------------------------------------------------------------------------
  63.  
  64. class Exception
  65. {
  66. protected:
  67.     LocationInCode        fThrowPoint;// Where was this thrown from        
  68.     OSStatus            fStatus;     // We'll use a long to handle QDErr, OSErr, etc.
  69.     
  70.     friend void            ThrowErrNum(const LocationInCode& where, long err);
  71.  
  72. public:
  73.     Exception(
  74.         const Exception& exc)
  75.     :    
  76.         fThrowPoint(exc.fThrowPoint),
  77.         fStatus(exc.fStatus)
  78.     {
  79.     }
  80.  
  81.     Exception(
  82.         const LocationInCode&    where,
  83.         OSStatus                status    = eGeneralErr)
  84.     :
  85.         fThrowPoint(where),
  86.         fStatus(status)
  87.     {
  88.     }
  89.  
  90.     virtual void        AboutToThrow(void) const;
  91.  
  92.     virtual bool        IsFatal(void) const;    // should app quit?
  93.     virtual bool        IsSilent(void) const;    // should we normally report it?
  94.  
  95.     virtual OSStatus    GetStatus(void) const;
  96.     virtual    OSStatus    SetStatus(OSStatus status);
  97. //    virtual long        GetMessage(void) const;
  98. //    virtual long        SetMessage(long message);
  99.  
  100.     virtual OSErr        GetOSErr(void) const;     // This is always a valid OSErr
  101.     virtual bool        GetErrorMessage(AEDesc& msg) const;
  102.     virtual bool        GetErrorString(Str255& msg) const;
  103.  
  104.     virtual void        Log() const;
  105.     virtual void        Report() const;
  106.     virtual OSErr        GetAEParams(   AERecord& evt, bool create) const;
  107.     virtual bool        PutErrorNumber(AERecord& evt) const;
  108.     virtual bool        PutErrorString(AERecord& evt) const;
  109.  
  110.     //
  111.     //    call these to provide better errors to AppleScript
  112.     //
  113.  
  114.     virtual bool        HasExpectedType() const;
  115.     virtual void        PutExpectedType(
  116.                             DescType expectedType,
  117.                             DescType actualType = 0,
  118.                             bool overwrite = false);
  119.  
  120.     virtual bool        HasOffendingObject() const;
  121.     virtual void        PutOffendingObject(
  122.                             const AEDesc& objectSpec,
  123.                             bool overwrite = false);
  124.  
  125.     virtual bool        HasOffendingParameter() const;
  126.     virtual void        PutOffendingParameter(
  127.                             AEKeyword param,
  128.                             bool overwrite = false);
  129.  
  130.     virtual bool        HasErrorParam(AEKeyword    param) const;
  131.     virtual void        PutErrorParamPtr(
  132.                             AEKeyword    param,
  133.                             DescType    type,
  134.                             const void*    data,
  135.                             Size        size,
  136.                             bool        overwrite = false);
  137.     virtual void        PutErrorParamDesc(
  138.                             AEKeyword        param,
  139.                             const AEDesc&    desc,
  140.                             bool            overwrite = false);
  141.     //
  142.     // for compatibility with integer-based systems
  143.     //
  144.     inline operator long() { return this->GetStatus(); } 
  145.  
  146.     //
  147.     // these routines pare the possible number of exceptions thrown down 
  148.     // to something reasonable. 
  149.     //
  150.     static OSStatus        vStandardizeExceptions(VAProc proc, va_list arg)        throw(Exception&);
  151.     static OSStatus        StandardizeExceptions(VAProc proc, ...)                    throw(Exception&);
  152.     static void            ReportExceptions(VAProc proc, ...)                        throw(Exception&);
  153.     static OSErr        CatchAEErrors(AppleEvent* evt, VAProc proc, ...)        throw();
  154.     static OSErr        CatchOSErrors(VAProc proc, ...)                            throw();
  155.     static OSStatus        CatchOSStatus(VAProc proc, ...)                            throw();
  156.     static void            MakeTextDesc(AEDesc& desc, const char *cstr);
  157.     static void            MakeTextDesc(AEDesc& desc, ConstStr255Param pstr);
  158.  
  159.     typedef void (*ReportExceptionProcPtr)(const Exception& exc);
  160.  
  161. public:
  162.     static ReportExceptionProcPtr    GetReportProc()            { return gReportProc;     }
  163.     static ReportExceptionProcPtr    SetReportProc(ReportExceptionProcPtr newProc);    
  164.  
  165. #if qDebug
  166.     static inline bool        LogExceptions()                    { return gLogExceptions; }
  167.     static inline bool        BreakOnThrow()                    { return gBreakOnThrow;     }
  168.     static bool                SetLogExceptions(bool newState);
  169.     static bool                SetBreakOnThrow(bool newState);
  170. #else
  171.     static inline bool        LogExceptions()                        { return false; }
  172.     static inline bool        BreakOnThrow()                        { return false; }
  173.     static inline bool        SetLogExceptions(bool /*newState*/)    { return false; }
  174.     static inline bool        SetBreakOnThrow(bool /*newState*/)    { return false; }
  175. #endif
  176.  
  177. private:
  178.     static ReportExceptionProcPtr    gReportProc;
  179.  
  180. #if qDebug
  181.     static bool                        gBreakOnThrow;
  182.     static bool                        gLogExceptions;
  183. #endif
  184. };
  185.  
  186. //------------------------------------------------------------------------------
  187.  
  188. class SilentException : public Exception
  189. {
  190. public:
  191.     SilentException(const SilentException& exc)    : Exception(exc)    {}
  192.     SilentException(const LocationInCode& where,
  193.                     OSStatus status) : Exception(where, status)        {}
  194.     virtual ~SilentException();
  195.  
  196.     virtual void        Log() const;
  197.     virtual void        Report() const;
  198.     virtual bool        IsSilent(void) const;
  199.     virtual OSErr        GetAEParams(AERecord& evt, bool create) const;
  200.  
  201. private:
  202.     typedef Exception    Inherited;
  203. };
  204.  
  205. //------------------------------------------------------------------------------
  206.  
  207. class StdException : public Exception
  208. {
  209. protected:
  210.     AEDesc        fErrParams; // AERecord contianing error info to return
  211.  
  212. public:
  213.     StdException(const StdException& exc);
  214.  
  215.     StdException(
  216.         const LocationInCode&    where,
  217.         OSStatus                status    = eGeneralErr)
  218.     :    Exception(where, status)
  219.     {
  220.         fErrParams.descriptorType    = typeNull;
  221.         fErrParams.dataHandle        = nil;
  222.     }
  223.  
  224.     virtual ~StdException();
  225.  
  226.     virtual void        Log() const;
  227.     virtual OSErr        GetAEParams(AERecord& evt, bool create) const;
  228.     virtual bool        GetErrorMessage(AEDesc& msg) const;
  229.     virtual bool        PutErrorString(AERecord& evt) const;
  230.  
  231.     virtual bool        CanAddErrorParam(AEKeyword param, bool overwrite);
  232.     virtual bool        HasErrorParam(AEKeyword    param) const;
  233.     virtual void        PutErrorParamPtr(
  234.                             AEKeyword    param,
  235.                             DescType    type,
  236.                             const void*    data,
  237.                             Size        size,
  238.                             bool        overwrite = false);
  239.     virtual void        PutErrorParamDesc(
  240.                             AEKeyword        param,
  241.                             const AEDesc&    desc,
  242.                             bool            overwrite = false);
  243.  
  244.     inline AEDesc&        GetErrorParams() { return fErrParams; }
  245.  
  246. private:
  247.     typedef Exception    Inherited;
  248. };
  249.  
  250. //
  251. //    Convenience functions
  252. //
  253. //    (These want to be inlines, but must be macros to get __FILE__ and __LINE__ to evaluate to
  254. //    useful values in the Throw() macros)
  255. //
  256.  
  257. inline OSErr ClipToOSErr(OSStatus val)        { return (val <= SHRT_MAX && val >= SHRT_MIN) ? (OSErr) val : eGeneralErr; }
  258.  
  259. #ifndef __NO_LOCATION_MACROS__
  260.  
  261.     // Macros to get __FILE__ and __LINE__ correct
  262.  
  263.     #define Throw                        GetLocationInCode().Throw
  264.     #define ThrowTypeError                GetLocationInCode().ThrowTypeError
  265.     #define ThrowKeywordError            GetLocationInCode().ThrowKeywordError
  266.     #define LogError                    GetLocationInCode().LogError
  267. //    #define Failure                        GetLocationInCode().Failure
  268.     #define DelegateAECall                GetLocationInCode().DelegateAECall
  269.  
  270.     #define FailOSStatus                GetLocationInCode().FailOSStatus
  271.     #define FailOSErr                    GetLocationInCode().FailOSErr
  272.     #define FailNIL                        GetLocationInCode().FailNIL
  273.     #define FailNILResource                GetLocationInCode().FailNILResource
  274.     #define ExpectedError                GetLocationInCode().ExpectedError
  275.  
  276.     #define Failure                        GetLocationInCode().Failure
  277.  
  278.     #define FailQDErr                    GetLocationInCode().FailQDErr
  279.     #define FailAEResult                GetLocationInCode().FailAEResult
  280.     #define FailAEKeyword                GetLocationInCode().FailAEKeyword
  281.     #define FailOptionalAEKeyword        GetLocationInCode().FailOptionalAEKeyword
  282.  
  283.     #define LogIfErr                    GetLocationInCode().LogIfErr
  284.     #define LogIfNotErr                    GetLocationInCode().LogIfNotErr
  285.  
  286.     #define FailResError()                FailOSErr(ResError());
  287.     #define FailMemError()                FailOSErr(MemError());
  288.  
  289.     #define UserCanceled                GetLocationInCode().UserCanceled
  290.  
  291.     //
  292.     // Requirements must always be met, but Assertions can be removed in non-debug builds
  293.     // as they are statements that are ASSUMED to always be true
  294.     //
  295.     // The log variants can be used where it is not acceptable to throw an error
  296.     //
  297.     // DebugWarn will break into the debugger with an explanation in debug builds
  298.     //
  299.  
  300.     #define Warning                        GetLocationInCode().Warning
  301.     #define WarnIf                        GetLocationInCode().WarnIf
  302.  
  303.     #define Assert                        GetLocationInCode().Assert
  304.     #define AssertPtrValid                GetLocationInCode().AssertPtrValid
  305.     #define AssertHandleValid            GetLocationInCode().AssertHandleValid
  306.  
  307.     #define Require                        GetLocationInCode().Require
  308.     #define RequirePtrValid                GetLocationInCode().RequirePtrValid
  309.     #define RequireHandleValid            GetLocationInCode().RequireHandleValid
  310.  
  311. #endif __NO_LOCATION_MACROS__
  312.  
  313. /*
  314. void    ReportException(Exception& exc, short action_code = 0, const unsigned char *message = nil);
  315. void    ReportOSError(OSErr    err, short action_code = 0, const unsigned char *message = nil);
  316. */
  317.  
  318. /*
  319. typedef void (*NotifyFailureProc)(OSErr err);
  320.  
  321. void    SetExceptionNotifyProc(NotifyFailureProc notifyProc);
  322. Boolean    ExceptionNotifyProcInstalled(void);
  323. void    NotifyFailure(OSErr err);
  324. */
  325.  
  326.  
  327.  
  328. #endif __EXCEPTIONS__
  329.